package com.google.ad.composelazylistdragitemorder

import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectDragGesturesAfterLongPress
import androidx.compose.foundation.gestures.scrollBy
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.google.ad.composelazylistdragitemorder.ui.theme.ComposeLazyListDragItemOrderTheme
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch

class MainActivity : ComponentActivity() {
    @OptIn(ExperimentalFoundationApi::class)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {


            ComposeLazyListDragItemOrderTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    Column {
                        DataLazyRwo()
                        Spacer(
                            Modifier
                                .fillMaxWidth()
                                .height(30.dp)
                                .background(Color.Green)
                        )
                        DataLazyColumn()

                    }
                }
            }
        }
    }

    @Composable
    @OptIn(ExperimentalFoundationApi::class)
    private fun DataLazyColumn() {
        val data = remember {
            mutableStateOf(mutableListOf<String>().apply {
                for (i in 0..100) {
                    add(i.toString())
                }
            })
        }
        val coroutineScope = rememberCoroutineScope()
        val overscrollJob = remember { mutableStateOf<Job?>(null) }
        val dragDropListState = rememberDragDropListState(onMove = { firstIndex, lastIndex ->
            data.value = data.value.swap(firstIndex, lastIndex).toMutableList()
        })
        LazyColumn(
            modifier = Modifier.dragGestureHandler(
                coroutineScope,
                dragDropListState,
                overscrollJob
            ),
            verticalArrangement = Arrangement.spacedBy(10.dp),
            state = dragDropListState.getLazyListState()
        ) {
            itemsIndexed(data.value) { index, item ->
                val displacementOffset =
                    if (index == dragDropListState.getCurrentIndexOfDraggedListItem()) {
                        dragDropListState.elementDisplacement.takeIf { it != 0f }
                    } else {
                        null
                    }
                val isBeingDragged = displacementOffset != null
                val scale = if (isBeingDragged) 1.5f else 1f
                val backGround = if (isBeingDragged) Color.Blue else Color.DarkGray

                val animateItemPlacement =
                    if (isBeingDragged) Modifier else Modifier
                        .animateItemPlacement()
                Box(modifier = animateItemPlacement
                    .graphicsLayer { translationY = displacementOffset ?: 0f }
                    .fillMaxWidth()
                    .height(100.dp)
                    .background(backGround)
                    .scale(scale)
                    .clickable {
                        Toast
                            .makeText(
                                this@MainActivity,
                                item,
                                Toast.LENGTH_SHORT
                            )
                            .show()
                    }) {
                    Text(
                        text = item,
                        modifier = Modifier.align(Alignment.Center),
                        color = Color.White,
                        fontSize = 20.sp
                    )
                }

            }
        }
    }



    @Composable
    @OptIn(ExperimentalFoundationApi::class)
    private fun DataLazyRwo() {
        val data = remember {
            mutableStateOf(mutableListOf<String>().apply {
                for (i in 0..100) {
                    add(i.toString())
                }
            })
        }
        val coroutineScope = rememberCoroutineScope()
        val overscrollJob = remember { mutableStateOf<Job?>(null) }
        val dragDropListState = rememberDragDropListState(onMove = { firstIndex, lastIndex ->
            data.value = data.value.swap(firstIndex, lastIndex).toMutableList()
        })
        LazyRow(
            modifier = Modifier.dragGestureHandler(
                coroutineScope,
                dragDropListState,
                overscrollJob
            ),
            horizontalArrangement = Arrangement.spacedBy(10.dp),
            state = dragDropListState.getLazyListState()
        ) {
            itemsIndexed(data.value) { index, item ->
                val displacementOffset =
                    if (index == dragDropListState.getCurrentIndexOfDraggedListItem()) {
                        dragDropListState.elementDisplacement.takeIf { it != 0f }
                    } else {
                        null
                    }
                val isBeingDragged = displacementOffset != null
                val scale = if (isBeingDragged) 1.5f else 1f
                val backGround = if (isBeingDragged) Color.Blue else Color.DarkGray

                val animateItemPlacement =
                    if (isBeingDragged) Modifier else Modifier
                        .animateItemPlacement()
                Box(modifier = animateItemPlacement
                    .graphicsLayer { translationX = displacementOffset ?: 0f }
                    .size(100.dp)
                    .background(backGround)
                    .scale(scale)
                    .clickable {
                        Toast
                            .makeText(
                                this@MainActivity,
                                item,
                                Toast.LENGTH_SHORT
                            )
                            .show()
                    }) {
                    Text(
                        text = item,
                        modifier = Modifier.align(Alignment.Center),
                        color = Color.White,
                        fontSize = 20.sp
                    )
                }

            }
        }
    }
}

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    Text(
        text = "Hello $name!",
        modifier = modifier
    )
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    ComposeLazyListDragItemOrderTheme {
        Greeting("Android")
    }
}


fun Modifier.dragGestureHandler(
    scope: CoroutineScope,
    itemListDragAndDropState: ItemListDragAndDropState,
    overscrollJob: MutableState<Job?>
): Modifier = this.pointerInput(Unit) {
    detectDragGesturesAfterLongPress(onDrag = { change, offset ->
        change.consume()
        itemListDragAndDropState.onDrag(offset)
        handleOverscrollJob(overscrollJob, scope, itemListDragAndDropState)
    }, onDragStart = { offset -> itemListDragAndDropState.onDragStart(offset) },
        onDragEnd = { itemListDragAndDropState.onDragInterrupted() },
        onDragCancel = { itemListDragAndDropState.onDragInterrupted() })
}

private fun handleOverscrollJob(
    overscrollJob: MutableState<Job?>,
    scope: CoroutineScope,
    itemListDragAndDropState: ItemListDragAndDropState
) {
    if (overscrollJob.value?.isActive == true) return
    val overscrollOffset = itemListDragAndDropState.checkForOverScroll()
    if (overscrollOffset != 0f) {
        overscrollJob.value = scope.launch {
            itemListDragAndDropState.getLazyListState().scrollBy(overscrollOffset)
        }
    } else {
        overscrollJob.value?.cancel()
    }
}